package com.dynamic.mybatis.core.parser.field;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.dynamic.mybatis.core.enums.Type;
import com.dynamic.mybatis.core.metadata.MappedStatementFieldValidator;
import com.dynamic.mybatis.core.metadata.MappedStatementMetaField;
import com.dynamic.mybatis.core.session.DynamicSqlSession;
import com.dynamic.mybatis.core.toolkit.BeanUtils;
import org.apache.ibatis.ognl.Ognl;
import org.apache.ibatis.ognl.OgnlException;
import org.apache.ibatis.session.Configuration;

import java.time.temporal.ChronoField;
import java.time.temporal.Temporal;
import java.util.*;

public abstract class DynamicMappedStatementFieldFormatter  extends DynamicMappedStatementFieldValidator{

    public DynamicMappedStatementFieldFormatter(DynamicSqlSession dynamicSqlSession) {
        super(dynamicSqlSession);
    }

    public  Object format(List<MappedStatementMetaField> field, Object rootParameter, Object parameter){
        if(CollectionUtils.isEmpty(field)){ return  parameter; }
        return  format(field.get(0),rootParameter,parameter);
    }

    public  Object format(MappedStatementMetaField field, Object rootParameter, Object parameter){
        if(field == null){ return  parameter; }
        return format(field,null,rootParameter,parameter);
    }

    /**
     *
     * @param field 字段信息
     * @param type  类型，用来解决field类型为数组，泛型问题
     * @param rootParameter 原生参数值
     * @param parameter  当前参数值
     * @return
     */
    public Object format(MappedStatementMetaField field,String type,Object rootParameter, Object parameter){
        MappedStatementFieldValidator validator = field.getValidator();
        if(!field.isVisible()){ return null; }

        boolean primitiveCheck = validator != null && parameter != null;

        type = StringUtils.isNotBlank(type) ?  type : field.getType();

        if(primitiveCheck && Type.DATE_TIME_TYPES.contains(type)){//日期、时间

            if(parameter instanceof Date){
                return   DateUtil.format((Date) parameter,validator.getDatePattern());
            }else if(parameter instanceof Temporal){
                return   DateUtil.format(LocalDateTimeUtil.of(((Temporal) parameter).getLong(ChronoField.MILLI_OF_SECOND)),validator.getDatePattern());
            }else if(parameter instanceof java.sql.Date){
                return   DateUtil.format(  LocalDateTimeUtil.of(((java.sql.Date) parameter).toLocalDate().getLong(ChronoField.MILLI_OF_SECOND)),validator.getDatePattern());
            }
            return parameter;

        }else if(primitiveCheck && CollectionUtils.isNotEmpty(validator.getEnums())){//枚举

           Object value =  validator.getEnums().get(Objects.toString(parameter));
           return  value != null ? value : parameter;

        }else if(Objects.equals(type,Type.StandardType.STRUCT.type) ){ //对象
            if( CollectionUtils.isEmpty(field.getChildren())){return parameter;}
            Map  parameterMap = BeanUtils.beanToMap(parameter);

            if(CollectionUtils.isEmpty(parameterMap)){ return parameter; }
            for (MappedStatementMetaField child : field.getChildren()) {

                //属性值为数组时，废弃使用泛型，否则递归调用无法进入字段类型为数组的判断程序
                String childType = Objects.equals(child.getType(),Type.StandardType.ARRAY.type) ? null : child.getGenericType();
                Object result =  format(child,childType,rootParameter, parameterMap.get(child.getField()));
                if(result != null){
                    if(child.getValidator() != null && CollectionUtils.isNotEmpty(child.getValidator().getEnums())){
                        parameterMap.put(child.getField()+"Text",result);
                        parameterMap.put(child.getField(),parameterMap.get(child.getField()));
                    }else {
                        parameterMap.put(child.getField(),result);
                    }
               }
               if(!child.isVisible()){
                   parameterMap.remove(child.getField());
               }
            }

        } else if(Objects.equals(type,Type.StandardType.ARRAY.type) ){//数组

           if(!(parameter instanceof Collection)){  return parameter;  }

            List list = ((List) parameter);
            for(int i = 0 ; i < list.size(); i++){
                if(list.get(i) == null){ continue;}
                Object result =  format(field,field.getGenericType(),rootParameter,list.get(i));
                if(result != null){
                    ((List)parameter).set(i,result);
                }
            }
        }
        if(validator  != null && validator.getOgnlExpression() != null){ //ognl校验
            try {
               return Ognl.getValue(validator.getOgnlExpression(),rootParameter);
            }catch (Exception e){
                return parameter;
            }
        }
        return parameter;
    }

    public static void main(String[] args) throws OgnlException {
        Map context = new HashMap();
        context.put("a",1);
        Object value = Ognl.getValue("a", context);




        Map context1 = new HashMap();
        List<Map<String,Object>> ls = new ArrayList();

        Map fc = new HashMap();
        fc.put("a","A01");
        fc.put("b","B01");
        fc.put("c","C01");
        ls.add(fc);

        Map fc2 = new HashMap();
        fc2.put("a","A02");
        fc2.put("b","B02");
        fc2.put("c","C02");
        ls.add(fc2);

        context1.put("list1", ls);

        String val = "B02";
        Object obj = Ognl.getValue(Ognl.parseExpression("list1.{?#this.a.equals(\"A01\") || #this.b=="+val+"}"), context1);
        System.out.println(obj);
    }


}
